#define _CRT_SECURE_NO_WARNINGS 1

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QString>
#include <QDebug>

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QCryptographicHash>

#include <QThreadStorage>
#include <QSqlError>
#include <QThread>

#include <iostream>
#include <stdio.h>

#include <winsock.h>
#include <Windows.h>

#include <string>
#include <map>
#include <thread>

#pragma comment(lib, "ws2_32.lib")

using namespace std;

map<SOCKET*, string> Clients;

unsigned __stdcall RecvConnet(void* param);
unsigned __stdcall RecvMSG(void* param);

// 添加全局线程存储
QThreadStorage<QSqlDatabase> threadLocalDB;

class Server : public QObject
{
    Q_OBJECT

    Q_PROPERTY(bool isRunning READ getisRunnning WRITE setisRunning NOTIFY isRunniungChange)

public:
    explicit Server(QObject *parent = nullptr)
    {
        initDatabase();
    }

    bool isRunning = false;

    SOCKET serverSocket;

    Q_INVOKABLE bool getisRunnning() { return isRunning; }
    Q_INVOKABLE void setisRunning(const bool& value)
    {
        isRunning = value;
        emit isRunniungChange(isRunning);
    }

    Q_INVOKABLE void startServer(const QString& ip, quint16 port)
    {
        WSADATA wsaDATA;
        WSAStartup(MAKEWORD(2, 2), &wsaDATA);
        if (LOBYTE(wsaDATA.wVersion) != 2 || HIBYTE(wsaDATA.wVersion) != 2)
            qDebug() << "Wrong Version\n";
        serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (SOCKET_ERROR == serverSocket)
            qDebug() << "Socket Error\n";

        SOCKADDR_IN sAddr = { 0 };
        sAddr.sin_family = AF_INET;
        sAddr.sin_addr.S_un.S_addr = inet_addr(ip.toStdString().c_str()); // IP
        sAddr.sin_port = htons(port); // 端口

        qDebug() << "IP: " << ip.toStdString().c_str() << " port: " << port;

        // 绑定
        int r = bind(serverSocket, (sockaddr*)&sAddr, sizeof sAddr);
        if (-1 == r)
            printf("Bind Error\n");

        // 监听
        r = listen(serverSocket, 10);
        if (r == -1)
            printf("Listen Error\n");
        else
            printf("服务器启动。\n");

        isRunning = true;

        RecvConnectThread = new std::thread([this]{
            _beginthreadex(0, 0, RecvConnet, this, 0, 0);
        });
    }

    Q_INVOKABLE void stopServer()
    {
        qDebug() << "Stop Server";

        if (!isRunning) return;

        isRunning = false;

        closesocket(serverSocket);
        serverSocket = INVALID_SOCKET;

        for (auto& client : Clients) {
            closesocket(*client.first);
            delete client.first;
        }
        Clients.clear();

        if (RecvConnectThread)
        {
            if(RecvConnectThread->joinable())
                RecvConnectThread->join();

            delete RecvConnectThread;
            RecvConnectThread = nullptr;
        }

        WSACleanup();

        emit statusChanged();
        logMessage("服务器已停止");
    }

    // 初始化数据库
    void initDatabase() {
        // 主线程初始化
        QSqlDatabase mainDB = QSqlDatabase::addDatabase("QSQLITE", "main_connection");
        mainDB.setDatabaseName("chat_server_users.db");
        if (!mainDB.open()) {
            qDebug() << "无法打开数据库:" << mainDB.lastError().text();
            return;
        }

        QSqlQuery query(mainDB);

        query.exec("CREATE TABLE IF NOT EXISTS users ("
                   "username TEXT PRIMARY KEY, "
                   "password TEXT NOT NULL)");

        query.exec("INSERT OR REPLACE INTO users (username, password) "
                   "VALUES ('test', '098f6bcd4621d373cade4e832627b4f6')"); // test : test

        query.exec("INSERT OR REPLACE INTO users (username, password) "
                   "VALUES ('testA', 'a7291eec016a1ca4c3abd1b531845009')");

        query.exec("INSERT OR REPLACE INTO users (username, password) "
                   "VALUES ('testB', 'e519d2744a05dc4445b6c88dae28eb74')");
    }

    Q_INVOKABLE bool registerUser(const QString &username, const QString &password) {
        if (username.isEmpty() || password.isEmpty()) return false;

        QString hashedPassword = hashPassword(password);
        QSqlQuery query;
        query.prepare("INSERT INTO users (username, password) VALUES (?, ?)");
        query.addBindValue(username);
        query.addBindValue(hashedPassword);

        return query.exec();
    }

    Q_INVOKABLE bool authenticate(const QString &username, const QString &password) {
        if (username.isEmpty() || password.isEmpty())
            return false;

        // 获取当前线程的数据库连接
        QSqlDatabase db = getThreadDB();
        if (!db.isOpen()) {
            qWarning() << "Database not open in thread";
            return false;
        }

        QSqlQuery query(db);
        query.prepare("SELECT password FROM users WHERE username = ?");
        query.addBindValue(username);

        if (!query.exec()) {
            qWarning() << "Authentication query failed:" << query.lastError().text();
            return false;
        }

        if (!query.next()) {
            return false; // 用户不存在
        }

        QString storedHash = query.value(0).toString();

        qDebug() << "storeHash: " << storedHash << " hashPassword: " << hashPassword(password);

        return storedHash == hashPassword(password);
    }

    Q_INVOKABLE bool changePassword(const QString &username, const QString &oldPassword,
                                    const QString &newPassword) {
        if (!authenticate(username, oldPassword)) return false;

        QString hashedPassword = hashPassword(newPassword);
        QSqlQuery query;
        query.prepare("UPDATE users SET password = ? WHERE username = ?");
        query.addBindValue(hashedPassword);
        query.addBindValue(username);

        return query.exec();
    }

signals:
    void isRunniungChange(const int& newValue);
    void statusChanged();
    void newMessage(QString msg);
    void clientConnected(QString name);
    void serverError(QString error);

private:
    std::thread RecvMsgThread;
    std::thread* RecvConnectThread;

    QSqlDatabase db;

    void logMessage(const std::string& message)
    {
        emit newMessage(QString::fromStdString(message));
    }

    // 密码哈希函数
    QString hashPassword(const QString &password) {
        QByteArray hash = QCryptographicHash::hash(
            password.toUtf8(), QCryptographicHash::Md5);
        return QString::fromLatin1(hash.toHex());
    }

    // 获取线程专用的数据库连接
    QSqlDatabase getThreadDB() {
        if (!threadLocalDB.hasLocalData()) {
            // 创建线程特定的连接名
            QString connectionName = QString("connection_%1")
                                         .arg(reinterpret_cast<quintptr>(QThread::currentThread()));

            QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
            db.setDatabaseName("chat_server_users.db");
            if (!db.open()) {
                qWarning() << "Failed to open database for thread:" << db.lastError().text();
            }
            threadLocalDB.setLocalData(db);
        }
        return threadLocalDB.localData();
    }
};

Server* server;

unsigned __stdcall RecvMSG(void* param)
{
    SOCKET* client = (SOCKET*)param;
    if (!client || *client == INVALID_SOCKET) return 1;

    string clientName = Clients[client];

    /*
    // 上线通知
    for (auto i : Clients)
    {
        if (i.first == client) continue;

        string msg = Clients[client] + " 加入了聊天室";
        send(*i.first, msg.data(), msg.size(), 0);
    }
    */

    // 正常通信
    char msg[256];
    string SendMsg;
    while (true)
    {
        int len = recv(*client, msg, 255, 0);
        if (len <= 0)
        {
            // 客户端断开连接
            qDebug() << "Client disconnected:" << clientName.c_str();

            // 通知其他客户端
            string leaveMsg = clientName + " 离开了聊天室";
            for (auto& i : Clients) {
                if (i.first != client) {
                    send(*i.first, leaveMsg.data(), leaveMsg.size(), 0);
                }
            }

            // 清理资源
            closesocket(*client);
            Clients.erase(client);
            delete client;

            return 0;
        }
        else
        {
            msg[len] = 0;

            qDebug() << "msg: " << msg;

            // 处理登录请求
            if (strncmp(msg, "LOGIN:", 6) == 0)
            {
                qDebug() << "login";

                char* username = msg + 6;
                char* password = strchr(username, ':');
                if (!password) continue;
                *password = 0;
                password++;

                // 使用线程安全的认证方法
                if (server->authenticate(username, password))
                {
                    qDebug() << "login succ";
                    int tmp = send(*client, "LOGIN_SUCCESS", 13, 0);
                    qDebug() << tmp;
                    Clients[client] = username;
                }
                else
                {
                    qDebug() << "login failed";
                    send(*client, "LOGIN_FAILED", 12, 0);
                }
                continue;
            }

            // 处理密码修改请求
            if (strncmp(msg, "CHANGE_PW:", 10) == 0) {
                char* oldPass = msg + 10;
                char* newPass = strchr(oldPass, ':');
                if (!newPass) continue;
                *newPass = 0;
                newPass++;

                if (server->changePassword(QString::fromStdString(clientName), oldPass, newPass)) {
                    send(*client, "PW_CHANGE_SUCCESS", 17, 0);
                } else {
                    send(*client, "PW_CHANGE_FAILED", 16, 0);
                }
                continue;
            }

            SendMsg = Clients[client] + ": " + msg;
            for (auto i : Clients)
            {
                send(*i.first, SendMsg.data(), SendMsg.size(), 0);
            }
            cout << SendMsg << endl;
        }
    }
}

unsigned __stdcall RecvConnet(void* param)
{
    Server* server = (Server*)param;

    int r = 0;
    while (server->isRunning)
    {
        // 接收连接
        SOCKET* clientSocket = new SOCKET();
        *clientSocket = accept(server->serverSocket, NULL, NULL);

        if(!server->isRunning)
        {
            delete clientSocket;
            break;
        }

        if (*clientSocket == INVALID_SOCKET)
        {
            int error = WSAGetLastError();
            if(error == WSAEINTR || error == WSAECONNRESET)
                qDebug() << "Accept interrupt";
            else
            {
                qDebug() << "Accept Error:" << error;
                emit server->serverError("接受连接失败: " + QString::number(error));
            }

            delete clientSocket;
            continue;
        }

        // 接收昵称
        char buff[256];
        r = recv(*clientSocket, buff, 255, NULL);
        if (r <= 0)
        {
            qDebug() << "Failed to get client name";
            closesocket(*clientSocket);
            delete clientSocket;
            continue;
        }

        buff[r] = 0;
        string ClientName;
        ClientName = buff;

        Clients.insert({ clientSocket, ClientName });

        qDebug() << "客户端连接 ： " << ClientName;
        emit server->clientConnected(QString::fromStdString(ClientName));

        HANDLE thread = (HANDLE)_beginthreadex(0, 0, RecvMSG, clientSocket, 0, 0);
        if (thread) CloseHandle(thread);
    }

    return 0;
}

int main(int argc, char *argv[])
{
    setbuf(stdout, NULL);
    fflush(stdout);

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    // 注册自定义对象到QML
    qmlRegisterType<Server>("ChatServer", 1, 0, "ChatServer");

    QQmlApplicationEngine engine;

    // 加载QML界面
    engine.loadFromModule("ChatServerQt2", "Main");

    // 创建并绑定服务器实例
    server = new Server();
    engine.rootContext()->setContextProperty("server", server);

    return app.exec();
}

#include "main.moc"
